package mware_lib;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Skeleton extends Thread {
    private Object obj;
    private Socket socket;
    private ObjectReferences objectReferences;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private String splitString = Config.splitString;

    public Skeleton(ObjectReferences objectReferences, Socket socket) {
        if(Config.DEBUGGER) System.out.println("Skeleton mit socket: " + socket.getInetAddress());
        this.socket = socket;
        this.objectReferences = objectReferences;
    }

    @Override
    public void run() {
        try {
            in = new ObjectInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());
            StubMessage stubMessage = (StubMessage) in.readObject();
            obj = objectReferences.getObj(stubMessage.getReference());
            if(Config.DEBUGGER) System.out.println("Skeleton mit obj class: " + obj.getClass());
            Class<?> cl = obj.getClass();
            Object objectString;
            if(Config.DEBUGGER) System.out.println("Skeleton mit stubMessage.getValues().length: " + stubMessage.getValues().length);
            if (stubMessage.getValues().length > 0) {
                Method method = cl.getMethod(stubMessage.getMethod(), stubMessage.getTypes());
                method.setAccessible(true);
                if(Config.DEBUGGER) System.out.println("Skeleton mit Method: " + stubMessage.getMethod() + " und params: " + Arrays.toString(stubMessage.getValues()));
                objectString = method.invoke(obj, stubMessage.getValues());
            } else {
                Method method = cl.getMethod(stubMessage.getMethod());
                method.setAccessible(true);
                if(Config.DEBUGGER) System.out.println("Skeleton mit Method: " + stubMessage.getMethod());
                objectString= method.invoke(obj);
            }
            if (objectString != null) {
                if(Config.DEBUGGER) System.out.println("Skeleton mit objectString: " + objectString.toString());
                out.writeObject(objectString.toString());
            } else {
                if(Config.DEBUGGER) System.out.println("Skeleton mit objectString = null");
                out.writeObject("");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            try {
                if(Config.DEBUGGER) System.out.println("RuntimeException : ERROR"+ splitString + e.getCause().getClass().toString() + splitString + e.getMessage());
                out.writeObject("ERROR"+ splitString + e.getCause().getClass().toString() + splitString + e.getMessage());
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        } catch (InvocationTargetException e) {
            try {
                if(Config.DEBUGGER) System.out.println("InvocationTargetException : ERROR" + splitString + e.getCause().getClass().toString() + splitString + e.getTargetException().getMessage());
                out.writeObject("ERROR" + splitString + e.getCause().getClass().toString() + splitString + e.getTargetException().getMessage());
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        } catch (Exception e) {
            try {
                if(Config.DEBUGGER) System.out.println("Exception : ERROR" + splitString + e.getCause().getClass().toString() + splitString + e.getMessage());
                out.writeObject("ERROR" + splitString + e.getCause().getClass().toString() + splitString + e.getMessage());
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}
